#include <iostream>

class Empty {
   using Int = int;
public:
   //virtual ~Empty() = default;
    virtual void Fun0() { std::cout << "func0" << std::endl; }
};

class EmptyToo : public Empty {
   void Fun1() { std::cout << "func1" << std::endl; }
};

class EmptyThree : public EmptyToo {};
class NonEmpty :  public EmptyToo {};

class EmptyTooV : virtual public Empty { void Fun0() { std::cout << "my func0" << std::endl; } };
class EmptyTwoV : virtual public Empty { void Fun1() { std::cout << "func1" << std::endl; } };
class EmptyThreeV : public EmptyTooV {};
class NonEmptyV : virtual public Empty, public EmptyTooV { };
class NonEmptyVV : public EmptyTooV, public EmptyTwoV { };

int main()
{
   std::cout << "sizeof(Empty): " << sizeof(Empty) << '\n';
   std::cout << "sizeof(EmptyToo): " << sizeof(EmptyToo) << '\n';
   std::cout << "sizeof(EmptyThree): " << sizeof(EmptyThree) << '\n';
   std::cout << "sizeof(NonEmpty): " << sizeof(NonEmpty) << '\n';
   std::cout << "sizeof(EmptyTooV): " << sizeof(EmptyTooV) << '\n';
   std::cout << "sizeof(EmptyThreeV): " << sizeof(EmptyThreeV) << '\n';
   std::cout << "sizeof(NonEmptyV): " << sizeof(NonEmptyV) << '\n';
   std::cout << "sizeof(NonEmptyVV: " << sizeof(NonEmptyVV) << '\n';

    EmptyToo b;
    const Empty* pb = &b;
    std::cout << typeid(*pb).name() << '\n';
    EmptyTooV b1;
    Empty* pb1 = &b1;
    std::cout << typeid(*pb1).name() << '\n';
    pb1->Fun0();
    std::cout << (typeid(*pb) == typeid(*pb1)) << std::endl;
}
